package com.ruicar.afs.cloud.image.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.image.condition.RevolveCondition;
import com.ruicar.afs.cloud.image.condition.ShowFileCondition;
import com.ruicar.afs.cloud.image.condition.UploadCondition;
import com.ruicar.afs.cloud.image.config.GwtFastdfsProperties;
import com.ruicar.afs.cloud.image.entity.ComAttachmentFile;
import com.ruicar.afs.cloud.image.entity.ComAttachmentManagement;
import com.ruicar.afs.cloud.image.enums.AttachmentClassEnum;
import com.ruicar.afs.cloud.image.enums.FileStatusEnum;
import com.ruicar.afs.cloud.image.enums.ResultCodeEnum;
import com.ruicar.afs.cloud.image.service.ComAttaManageService;
import com.ruicar.afs.cloud.image.service.ComAttachmentFileService;
import com.ruicar.afs.cloud.image.store.enums.IsViewEnum;
import com.ruicar.afs.cloud.image.store.feign.ImageStoreApiFeign;
import com.ruicar.afs.cloud.image.util.ImageUtil;
import com.ruicar.afs.cloud.image.vo.UploadInputVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description:
 * @Author: fangchenliang
 * @Date: 2020/6/10 17:29
 */
@RestController
@AllArgsConstructor
@Slf4j
@RequestMapping("/upload")
@Api(value = "image", description = "影像上传")
public class AfsUploadFileController {

    private ComAttaManageService comAttaManageService;

    private ComAttachmentFileService comAttachmentFileService;

    private ImageStoreApiFeign imageStoreApiFeign;


    private GwtFastdfsProperties tokenProperties;

    private ImageUtil imageUtil;

    /**
     * 获取token信息
     *
     * @return
     */
    public String getAuthorization() {
        Map<String, String> data = new HashMap<>();
        data.put("client_id", tokenProperties.getClientId());
        data.put("client_secret", tokenProperties.getClientSecret());
        data.put("grant_type", tokenProperties.getGrantType());
        JSONObject jsonObject = imageStoreApiFeign.getTokenInfo(data);
        String authorization = jsonObject.getString("token_type") + " " + jsonObject.getString("access_token");
        return authorization;
    }

    @PostMapping(value = "/getUploadList")
    @ApiOperation(value = "根据业务场景和前端参数获取影像件类型")
    public IResponse<List<ComAttachmentManagement>> getUploadList(@RequestBody UploadCondition uploadCondition) {

        /**影像件上传列表由两部分组成：
         * 1.已上传文件的影像件类型，必须全部展示,是否标识是否必传，需要跑规则;
         *  （主要是由于审批更改融资信息之后退回重新上传，与第一次跑规则出来的影像件类型会存在差异，但之前上传的文件必须展示）;
         * 2.通过业务参数跑批出来的影像件类型。
         */
        String busiNo = uploadCondition.getBusiNo();
        String busiType = uploadCondition.getBusiType();
        List<ComAttachmentManagement> uploadListData = null;
        if (busiNo != null && busiType != null) {
            List<ComAttachmentManagement> attachmentManagementFileList = comAttaManageService.getAllFileList(uploadCondition.getBusiNo(), uploadCondition.getBusiType());
            if (attachmentManagementFileList.size() > 0) {
                attachmentManagementFileList.forEach(attachmentManagement -> {
                    comAttaManageService.comAttachmentManagementHitRule(uploadCondition.getBusiData(), attachmentManagement);
                });
            }
            List<ComAttachmentManagement> attachmentManagementRuleList = comAttaManageService.getAttaListByRule(uploadCondition.getBusiData(), uploadCondition.getBusiType());
            Map<Long, ComAttachmentManagement> attaFileMap = attachmentManagementFileList.stream().collect(Collectors.toMap(ComAttachmentManagement::getId, comAttachmentManagement -> comAttachmentManagement));
            Iterator it = attachmentManagementRuleList.iterator();
            /**合并两部分的影像件类型*/
            while (it.hasNext()) {
                ComAttachmentManagement comAttachmentManagement = (ComAttachmentManagement) it.next();
                if (!attaFileMap.containsKey(comAttachmentManagement.getId())) {
                    attachmentManagementFileList.add(comAttachmentManagement);
                }
            }
            uploadListData = comAttaManageService.invokeParent(attachmentManagementFileList);
        }
        return IResponse.success(uploadListData);

    }

    @PostMapping(value = "/getUploadListByGroup")
    @ApiOperation(value = "根据业务场景和前端参数获取影像件类型")
    public IResponse<List<ComAttachmentManagement>> getUploadListByGroup(@RequestBody UploadCondition uploadCondition) {
        String busiNo = uploadCondition.getBusiNo();
        String busiType = uploadCondition.getBusiType();
        log.info("根据业务场景和前端参数获取影像件类型，规则报文:{}",uploadCondition.getBusiData());
        List<ComAttachmentManagement> uploadListData = null;
        if (busiNo != null && busiType != null) {
            List<ComAttachmentManagement> managementList = comAttaManageService.getManagementByRuleGroup(uploadCondition.getBusiData(), uploadCondition.getBusiType());
            managementList.forEach(comAttachmentManagement -> {
                List<ComAttachmentFile> fileList = comAttachmentFileService.list(Wrappers.<ComAttachmentFile>query().lambda().
                        eq(ComAttachmentFile::getAttachmentCode, String.valueOf(comAttachmentManagement.getId()))
                        .eq(ComAttachmentFile::getBusiNo, busiNo));
                if(!CollectionUtils.isEmpty(fileList)){
                    List<ComAttachmentFile> standardFiles=fileList.stream().filter(comfile->comfile.getFileStatus().equals(FileStatusEnum.STANDARD.getCode())).collect(Collectors.toList());
                    List<ComAttachmentFile> draftFiles=fileList.stream().filter(comfile->comfile.getFileStatus().equals(FileStatusEnum.DRAFT.getCode())).collect(Collectors.toList());
                    List<ComAttachmentFile> waitApproveFiles=fileList.stream().filter(comfile->comfile.getFileStatus().equals(FileStatusEnum.WAITAPPROVE.getCode())).collect(Collectors.toList());
                    comAttachmentManagement.setFileList(fileList);
                    comAttachmentManagement.setValidNums((CollectionUtils.isEmpty(standardFiles)?0:standardFiles.size())+(CollectionUtils.isEmpty(draftFiles)?0:draftFiles.size())+(CollectionUtils.isEmpty(waitApproveFiles)?0:waitApproveFiles.size()));
                }

            });
            uploadListData = comAttaManageService.invokeParent(managementList);
        }
        return IResponse.success(uploadListData);
    }

    @PostMapping(value = "/getAllFileList")
    @ApiOperation(value = "根据业务场景和业务编号号获取影像件文件和类型")
    public IResponse<List<ComAttachmentManagement>> getAllFileList(String busiNo, String busiType) {
        List<ComAttachmentManagement> uploadFileList = new ArrayList<>();
        Map map = new HashMap();
        map.put("busiNode", busiType.split(","));
        List list = Arrays.asList(busiType.split(","));
        List<ComAttachmentFile> fileList = comAttachmentFileService.findUploadFileByBusiNo(busiNo, list);
        Map<String, List<ComAttachmentFile>> filesMap = fileList.stream().collect(Collectors.groupingBy(ComAttachmentFile::getAttachmentCode));
        Iterator it = filesMap.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next().toString();
            List<ComAttachmentManagement> attaList = comAttaManageService.list(
                    Wrappers.<ComAttachmentManagement>query().lambda()
                            .eq(ComAttachmentManagement::getId, Long.valueOf(key)));
            attaList.get(0).setFileList(filesMap.get(key));
            uploadFileList = Stream.of(uploadFileList, attaList)
                    .flatMap(Collection::stream)
                    .distinct()
                    .collect(Collectors.toList());
        }
        return IResponse.success(uploadFileList);
    }

    @PostMapping(value = "/saveAttachmentFile")
    @ApiOperation(value = "上传影像件")
    public IResponse<ComAttachmentFile> uploadFile(@RequestParam("attachmentId") String attachmentId,
                                                @RequestParam("attachmentName") String attachmentName,
                                                @RequestParam("fileType") String fileType,
                                                @RequestParam("fileName") String fileName,
                                                @RequestParam("fileMd5") String fileMd5,
                                                @RequestParam("applyNo") String busiNo,
                                                @RequestParam("belongNo") String belongNo) {
        UploadInputVo uploadInputVo = new UploadInputVo();
        ComAttachmentManagement comAttachmentManagement=comAttaManageService.getById(Long.valueOf(attachmentId));
        uploadInputVo.setAttachmentId(attachmentId);
        uploadInputVo.setAttachmentName(attachmentName);
        uploadInputVo.setFileType(fileType);
        uploadInputVo.setFileName(fileName);
        uploadInputVo.setFileMd5(fileMd5);
        uploadInputVo.setBusiNo(busiNo);
        uploadInputVo.setBelongNo(belongNo);
        uploadInputVo.setArchiveClass(comAttachmentManagement.getArchiveClass());
        uploadInputVo.setFileSource("com_attachment_management");
        ComAttachmentFile file=comAttachmentFileService.saveComAttachmentFile(uploadInputVo);
        return IResponse.success(file);
    }

    @PostMapping(value = "/viewFile")
    @ApiOperation(value = "预览图片")
    public IResponse<ComAttachmentManagement> downloadFileByType(@RequestBody ShowFileCondition showFileCondition) {
        String busiNo=showFileCondition.getBusiNo();
        String belongNo=showFileCondition.getBelongNo();
        String version= StringUtils.isBlank(showFileCondition.getVersion())?"":showFileCondition.getVersion();
        ComAttachmentManagement comAttachmentManagement = showFileCondition.getComAttachmentManagement();
        List<ComAttachmentFile> outList=new ArrayList<>();
        if(!ObjectUtils.isEmpty(comAttachmentManagement)) {
            outList = comAttaManageService.getFileList(outList, busiNo, belongNo, comAttachmentManagement,version);
        }
        if(!CollectionUtils.isEmpty(outList)){
            List<ComAttachmentFile> standardFiles=outList.stream().filter(comfile->comfile.getFileStatus().equals(FileStatusEnum.STANDARD.getCode())).collect(Collectors.toList());
            List<ComAttachmentFile> draftFiles=outList.stream().filter(comfile->comfile.getFileStatus().equals(FileStatusEnum.DRAFT.getCode())).collect(Collectors.toList());
            List<ComAttachmentFile> waitApproveFiles=outList.stream().filter(comfile->comfile.getFileStatus().equals(FileStatusEnum.WAITAPPROVE.getCode())).collect(Collectors.toList());
            comAttachmentManagement.setValidNums((CollectionUtils.isEmpty(standardFiles)?0:standardFiles.size())+(CollectionUtils.isEmpty(draftFiles)?0:draftFiles.size())+(CollectionUtils.isEmpty(waitApproveFiles)?0:waitApproveFiles.size()));
        }
        comAttachmentManagement.setFileList(outList);
        return IResponse.success(comAttachmentManagement);
    }

    @GetMapping(value = "/getBlob/{fileType}/{md5}")
    @ApiOperation(value = "预览图片")
    public void getBlob(HttpServletResponse response, @PathVariable("md5") String md5, @PathVariable("fileType") String fileType) throws Exception {

        if (fileType.equals("pdf")) {
            response.setContentType(MediaType.APPLICATION_PDF_VALUE);
        }else if(fileType.equals("mp4")){
            response.setContentType( "video/mp4");
        }else if(fileType.equals("png") || fileType.equals("PNG")){
            response.setContentType(MediaType.IMAGE_PNG_VALUE);
        }else if(fileType.equals("jpg") || fileType.equals("JPG")){
            response.setContentType(MediaType.IMAGE_JPEG_VALUE);
        } else {
            response.setContentType(MediaType.ALL_VALUE);
        }

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", getAuthorization());
        byte[] fileByte = imageStoreApiFeign.downFile(md5, tokenProperties.getSceneId(), "", IsViewEnum.download.getCode(), null, headers);
        response.getOutputStream().write(fileByte);
        response.getOutputStream().flush();
    }

    @PostMapping(value = "/updateFile")
    @ApiOperation(value = "更新图片信息")
    public IResponse<ComAttachmentFile> updateFile(@RequestBody JSONObject fileParam) {
        JSONArray jsonArray = fileParam.getJSONArray("fileList");
        String attachmentId = fileParam.getString("attachmentId");
        log.info(fileParam.toString());
        String[] msg = {""};
        if (jsonArray != null && jsonArray.size() > 0) {
            for (int i = 0; i < jsonArray.size(); i++) {
                Map<String, String> filemap = (Map<String, String>) jsonArray.get(i);
                ComAttachmentFile file = comAttachmentFileService.getById(Long.valueOf(filemap.get("id")));
                if (file != null) {
                    file.setAttachmentCode(attachmentId);
                    file.setAttachmentName(comAttaManageService.getOne(Wrappers.<ComAttachmentManagement>lambdaQuery()
                            .eq(ComAttachmentManagement::getId,Long.valueOf(attachmentId)),false).getAttachmentName());
                    comAttachmentFileService.updateById(file);
                    msg[0] = "更新成功";
                } else {
                    msg[0] = "未找到相应图片:" + filemap.get("id");
                }
            }
        }
        return IResponse.success(msg[0]);
    }

    @PostMapping(value = "/deleteFile")
    @ApiOperation(value = "更新图片信息")
    public IResponse<ComAttachmentFile> deleteFile(@RequestBody JSONObject fileList) {
        JSONArray jsonArray = fileList.getJSONArray("fileList");
        log.info(fileList.toString());
        String[] msg = {""};
        if (jsonArray != null && jsonArray.size() > 0) {
            for (int i = 0; i < jsonArray.size(); i++) {
                Map<String, String> filemap = (Map<String, String>) jsonArray.get(i);
                ComAttachmentFile file = comAttachmentFileService.getById(Long.valueOf(filemap.get("id")));
                if (file != null) {
                    comAttachmentFileService.removeById(file);
                    msg[0] = "删除成功";
                } else {
                    msg[0] = "未找到相应图片:" + filemap.get("id");
                }
            }
        }
        return IResponse.success(msg[0]);
    }

    @PostMapping(value = "/zipDownload")
    @ApiOperation(value = "更新图片信息")
    public void zipDownload(@RequestBody JSONObject fileList) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse resp = attributes.getResponse();
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", getAuthorization());
        JSONArray jsonArray = fileList.getJSONArray("data");
        List fileByteList = new ArrayList<>();
        if (jsonArray != null && jsonArray.size() > 0) {
            for (int i = 0; i < jsonArray.size(); i++) {
                Map<String, String> filemap = (Map<String, String>) jsonArray.get(i);
                byte[] result = imageStoreApiFeign.downFile(filemap.get("md5Value"),
                        filemap.get("downloadsceneid"),
                        filemap.get("filename"),
                        filemap.get("isView"),
                        filemap.get("isThumb"), headers);
                Map map = new HashMap();
                map.put("byte", result);
                map.put("name", filemap.get("filename"));
                fileByteList.add(map);
            }
        }
    }

    @PostMapping(value = "/checkFile")
    @ApiOperation(value = "根据前端参数检查文件是否已上传完整")
    public IResponse checkFile(@RequestBody UploadCondition uploadCondition) {
        String busiNo = uploadCondition.getBusiNo();
        String busiType = uploadCondition.getBusiType();
        log.info("==={}检查文件是否已上传完整开始==",busiNo);
        List<ComAttachmentManagement> uploadListData = null;
        if (!ObjectUtils.isEmpty(busiNo)&& !ObjectUtils.isEmpty(busiType)) {
            List<String> errorMsgList= new ArrayList<>();
            List<ComAttachmentManagement> managementList = comAttaManageService.getManagementByRuleGroup(uploadCondition.getBusiData(), uploadCondition.getBusiType());
            managementList.forEach(comAttachmentManagement -> {
                List<String> status=new ArrayList<>();
                status.add(FileStatusEnum.DRAFT.getCode());
                status.add(FileStatusEnum.STANDARD.getCode());
                status.add(FileStatusEnum.REVISE.getCode());
                status.add(FileStatusEnum.WAITAPPROVE.getCode());
                List<ComAttachmentFile> fileList = comAttachmentFileService.list(Wrappers.<ComAttachmentFile>query().lambda().
                        eq(ComAttachmentFile::getAttachmentCode, String.valueOf(comAttachmentManagement.getId()))
                        .eq(ComAttachmentFile::getBusiNo, busiNo)
                        .in(ComAttachmentFile::getFileStatus,status));
                comAttachmentManagement.setFileList(fileList);
                if(comAttachmentManagement.getAttachmentClass()==AttachmentClassEnum.SUBCLASS.getCode() &&comAttachmentManagement.getNeedNums()>fileList.size()){
                    errorMsgList.add(comAttachmentManagement.getAttachmentName());
                }
            });

            Map<Long, List<ComAttachmentManagement>> subclassAttachmentManagementMaps = managementList.stream()
            .collect(Collectors.groupingBy(ComAttachmentManagement::getParentId));
            managementList.forEach(management->{
                if(management.getAttachmentClass()==AttachmentClassEnum.GROUP.getCode()){
                    int filenums=0;
                    List<ComAttachmentManagement> attachmentManagementList=subclassAttachmentManagementMaps.get(management.getId());
                    if(!CollectionUtils.isEmpty(attachmentManagementList)){
                        for(ComAttachmentManagement comAttachmentManagement : attachmentManagementList){
                            if(comAttachmentManagement.getFileList().size()>0){
                                filenums=filenums+1;
                            }
                        }
                        if(management.getNeedNums()>filenums){
                            errorMsgList.add(management.getAttachmentName());
                        }
                    }
                }
            });
            if(errorMsgList.size()>0){
                return IResponse.fail(errorMsgList+"文件不全！");
            }else{
                return IResponse.success("文件校验成功！");
            }
        }else {
            return IResponse.fail(busiNo+"未找相应数据,请核实附件信息！");
        }
    }

    @PostMapping(value = "/revolveFile")
    @ApiOperation(value = "旋转保存图片")
    public IResponse revolveFile(@RequestBody RevolveCondition revolveCondition){
        String md5=revolveCondition.getFileId();
        String fileName=revolveCondition.getFileName();
        String fileType=revolveCondition.getFileType();
        BigDecimal de=new BigDecimal(revolveCondition.getDegree());
        BigDecimal[] results = de.divideAndRemainder(BigDecimal.valueOf(360));
        int degree=0;
        if(results[1].compareTo(BigDecimal.ZERO)==-1){
            degree=results[1].add(BigDecimal.valueOf(360)).intValue();
        }else {
            degree = results[1].intValue();
        }
        JSONObject resultJson=comAttachmentFileService.revolveFile(md5,fileName,fileType,degree);
        log.info("旋转后上传OSS返回报文：",resultJson.toJSONString());
        Boolean requestOK = resultJson.containsKey("success") && resultJson.getInteger("success") == ResultCodeEnum.SUCCESS.getCode();
        String message = resultJson.containsKey("message") ? resultJson.getString("message") : "";
        if (requestOK) {
            JSONObject resultData = resultJson.containsKey("data") ? resultJson.getJSONObject("data") : new JSONObject();
            Boolean uploadOK = resultData.containsKey("success") && resultData.getBoolean("success");
            if (uploadOK) {
                message = resultData.containsKey("message") ? resultData.getString("message") : "";
                String fileId=resultData.getString("md5");
                ComAttachmentFile comAttachmentFile=comAttachmentFileService.getById(revolveCondition.getId());
                comAttachmentFile.setFileId(fileId);
                comAttachmentFileService.updateById(comAttachmentFile);
                return IResponse.success(message);
            } else {
                log.error("上传文件到OSS：上传失败" + message);
                return IResponse.fail(message);
            }
        } else {
            log.error("上传文件到OSS：请求失败" + message);
            return IResponse.fail(message);
        }
    }
}
